package org.linlinjava.litemall.core.tool.wxpayscore;

import cn.com.ejiakanghu.core.enums.ResultCode;
import cn.com.ejiakanghu.core.exception.CheckException;
import cn.com.ejiakanghu.core.exceptions.BizException;
import cn.com.ejiakanghu.core.log.wxpayscore.LogWxPayScore;
import cn.com.ejiakanghu.core.utils.RespUtil;
import cn.com.ejiakanghu.core.vo.BaseResult;
import com.github.binarywang.wxpay.bean.payscore.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.PayScoreService;
import org.apache.commons.io.IOUtils;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import static org.linlinjava.litemall.db.config.WxPayScoreConfig.MAX_DEPOSIT_FEN;
import static org.linlinjava.litemall.db.config.WxPayScoreConfig.MAX_DEPOSIT_YUAN;

/**
 * @author houzb
 * @Description
 * @create 2021-12-09 17:56
 */
@Component
public class WxPayScoreTool {
    private Logger logger = LoggerFactory.getLogger(WxPayScoreTool.class);
    @Autowired
    private PayScoreService payScoreService;
    @Autowired
    private WxPayConfig wxPayConfig;

    /**
     *  创建支付分订单
     * @param openId
     * @param orderCode
     * @param fee
     * @return
     */
    public BaseResult<WxPayScoreResult> createPayScoreOrder(String openId, String orderCode, int fee) throws CheckException {
        if(fee > MAX_DEPOSIT_FEN) {
            logger.error("支付分免押订单，超出最高免押金额{},{},{},{}", MAX_DEPOSIT_YUAN, openId, orderCode, fee);
            throw new CheckException(ResultCode.WX_NODEPOSIT_ERR_MAX_DEPOSIT);
        }
        WxPayScoreRequest payScoreRequest = new WxPayScoreRequest();
        payScoreRequest.setOutOrderNo(orderCode);
        payScoreRequest.setNotifyUrl(wxPayConfig.getPayScoreNotifyUrl());
        payScoreRequest.setServiceId(wxPayConfig.getServiceId());
        payScoreRequest.setOpenid(openId);
        //商品名称
        payScoreRequest.setServiceIntroduction("围老医疗辅助器械租借");
        payScoreRequest.setAppid(wxPayConfig.getAppId());
        TimeRange timeRange = new TimeRange();
        timeRange.setStartTime("OnAccept");
        payScoreRequest.setTimeRange(timeRange);
        payScoreRequest.setNeedUserConfirm(true);
        RiskFund riskFund = new RiskFund();
        /**
         * 填名称为
         * DEPOSIT：押金
         * ADVANCE：预付款
         * CASH_DEPOSIT：保证金
         * 【先享模式】（评估不通过不可使用服务）可填名称为
         * ESTIMATE_ORDER_COST：预估订单费用
         */
        riskFund.setName("DEPOSIT");
        riskFund.setAmount(fee);
        payScoreRequest.setRiskFund(riskFund);
        WxPayScoreResult wxPayScoreResult = null;
        try {
            wxPayScoreResult = payScoreService.createServiceOrder(payScoreRequest);
        } catch (WxPayException e) {
            e.printStackTrace();
            LogWxPayScore.logger.error("微信支付分-创建定情请求失败:{},{},{}", openId, orderCode, fee);
            return RespUtil.fail();
        }
        LogWxPayScore.debug("微信支付分-创建支付分订单,参数={},结果{}", JacksonUtil.gson.toJson(payScoreRequest), wxPayScoreResult != null ? JacksonUtil.gson.toJson(wxPayScoreResult) : "null");
        if(wxPayScoreResult == null) {
            return RespUtil.fail(ResultCode.WX_NODEPOSIT_ERR_CREATE_FAIL);
        }
        return RespUtil.success(wxPayScoreResult);
    }

    /**
     * 取消支付分订单
     * @param bigOrderCode
     * @param cancelReason
     * @return
     */
    public BaseResult payScoreCancel(String bigOrderCode, String cancelReason) {
        String reason = cancelReason == null ? "订单取消" :cancelReason;
        WxPayScoreResult wxPayScoreResult = null;
        try {
            wxPayScoreResult = payScoreService.cancelServiceOrder(bigOrderCode, reason);
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new BizException("取消订单失败");
        }
        return RespUtil.success(wxPayScoreResult);
    }

    /**
     * 查询支付分订单
     * @param orderCode
     * @return
     */
    public WxPayScoreResult payScoreQuery(String orderCode) {
        WxPayScoreResult wxPayScoreResult = null;
        try {
            wxPayScoreResult = payScoreService.queryServiceOrder(orderCode, null);
        } catch (WxPayException e) {
            e.printStackTrace();
            return null;
        }
        return wxPayScoreResult;
    }

    public BaseResult payScoreModify(LitemallOrder order, String reason) {
        Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();
        WxPayScoreRequest payScoreRequest = new WxPayScoreRequest();
        payScoreRequest.setOutOrderNo(order.getOrderSn());
        List<PostPayment> postPayments = new ArrayList<>();
        PostPayment postPayment = new PostPayment();
        postPayment.setName(order.getOrderSn());
        postPayment.setAmount(totalFee);
        postPayments.add(postPayment);
        payScoreRequest.setPostPayments(postPayments);
        payScoreRequest.setTotalAmount(totalFee);
        payScoreRequest.setReason(reason);

        WxPayScoreResult wxPayScoreResult = null;
        try {
            wxPayScoreResult = payScoreService.modifyServiceOrder(payScoreRequest);
        } catch (WxPayException e) {
            e.printStackTrace();
            return RespUtil.fail();
        }
        return RespUtil.success();
    }

    /**
     * 支付分完结订单
     * @param bigOrderCode
     * @return
     */
    public BaseResult payScoreComplete(String bigOrderCode, BigDecimal totalCostFee, LocalDateTime signTime) {
        Integer totalFee = totalCostFee.multiply(new BigDecimal(100)).intValue();
        WxPayScoreRequest payScoreRequest = new WxPayScoreRequest();
        payScoreRequest.setOutOrderNo(bigOrderCode);
        List<PostPayment> postPayments = new ArrayList<>();
        PostPayment postPayment = new PostPayment();
        //商品名
        postPayment.setName("设备租借费用");
        postPayment.setAmount(totalFee);
        postPayments.add(postPayment);
        payScoreRequest.setPostPayments(postPayments);
        TimeRange timeRange = new TimeRange();
        timeRange.setStartTime(signTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        LocalDateTime overTime = LocalDateTime.now().minusMinutes(1);
        Duration duration = Duration.between(signTime, overTime);
        boolean isErr = duration.toMillis() < 0;
        if(isErr) {
            overTime = signTime.plusSeconds(1);
        }
        timeRange.setEndTime(overTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        payScoreRequest.setTimeRange(timeRange);
        payScoreRequest.setTotalAmount(totalFee);

        WxPayScoreResult wxPayScoreResult = null;
        try {
            wxPayScoreResult = payScoreService.completeServiceOrder(payScoreRequest);
        } catch (WxPayException e) {
            e.printStackTrace();
            return RespUtil.fail();
        }
        LogWxPayScore.debug("支付分完结订单:{}, {}", bigOrderCode, wxPayScoreResult != null ? JacksonUtil.gson.toJson(wxPayScoreResult) : "null");
        return RespUtil.success(wxPayScoreResult);
    }


    /**
     * 支付分通知结果处理
     * @param request
     * @return
     * @throws IOException
     * @throws WxPayException
     */
    public WxPayScoreResult payScoreNotifyRst(HttpServletRequest request) throws IOException, WxPayException {
        String data = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        PayScoreNotifyData payScoreNotifyData = payScoreService.parseNotifyData(data, null);
        WxPayScoreResult payScoreResult =  payScoreService.decryptNotifyDataResource(payScoreNotifyData);
        return payScoreResult;
    }

}
